package com.scy.hospitalmanager.until;

import com.google.gson.Gson;
import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.MACSigner;
import com.nimbusds.jose.crypto.MACVerifier;
import lombok.SneakyThrows;
import net.minidev.json.JSONObject;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description: token生成类
 * @ClassName: TokenUtil
 * @Author: KuonnjiArisu
 * @Date: 2021/8/24 14:31
 * @Version: 1.0
 */
public class TokenUtil {
    private static final byte[] SECRET_KEY = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".getBytes();


    /**
     * @Author KuonnjiAirsu
     * @Description //TODO token创建时间
     */
    //token 失效时间
    private static final String INVALID_TIME_KEY= "__cas_invalid_time";


    /**
     * @Author KuonnjiAirsu
     * @Description //TODO 生成token
     * @Param payloadMap //用户数据信息
     * @Param invalidTime //失效token
     * @return
     */
    @SneakyThrows
    public static String createToken(Map<String,Object> payloadMap, long createTime, long invalidTime){
        try {
            if(invalidTime<createTime){
                System.out.println("====> 失效时间必须大于创建时间...");
                return null;
            }
            if (CollectionUtils.isEmpty(payloadMap)){
                payloadMap = new HashMap<>();
            }
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date date = new Date();
            String format = sdf.format(date);
            payloadMap.put("currentTime",format);
            payloadMap.put(INVALID_TIME_KEY,invalidTime);
            System.out.println("====> 生成token用户信息为:"+ GsonUtil.toJson(payloadMap));
            /** 建立头部header
             *JWSHeader参数：1.加密算法法则，2.类型，3.采用HS256加密算法法则
             *
             *Payload 建立一个负荷
             *
             * JWSAlgorithm类中有所有算法法则，可以直接调用
             */
            //将头部和载荷结合在一起
            JWSObject jwsObject = new JWSObject(new JWSHeader(JWSAlgorithm.HS256),
                    new Payload(new JSONObject(payloadMap)));
            //建立密钥
            JWSSigner jwsSigner = new MACSigner(SECRET_KEY);
            //签名
            jwsObject.sign(jwsSigner);
            //生成token
            return jwsObject.serialize();
        } catch (Exception e){
            System.out.println("====> 创建token失败"+e);
            e.printStackTrace();
            return null;
        }
    }


    /**
     * @Author KuonnjiAirsu
     * @Description //TODO 解析出token的Payload部分数据信息
     * @Param token
     * @return
     */
    @SneakyThrows
    public static Map<String,Object> parsePayloadData(String token){
        try{
            if (StringUtils.isEmpty(token)){
                return null;
            }
            //解析token
            JWSObject jwsObject = JWSObject.parse(token);
            //获取到载荷
            Payload payload = jwsObject.getPayload();
            //建立解锁密钥
            JWSVerifier jwsVerifier = new MACVerifier(SECRET_KEY);
            Map<String,Object>resultMap = null;
            //判断token
            if (jwsObject.verify(jwsVerifier)){
                //载荷的数据解析成json对象
                JSONObject jsonObject = payload.toJSONObject();
                Gson gson = new Gson();
                resultMap = gson.fromJson(gson.toJson(jsonObject),Map.class);
            }
            return resultMap;
        } catch (ParseException e) {
            System.out.println("====> 解析token失败"+e);
            e.printStackTrace();
            return null;
        }
    }


        /**
         * @Author KuonnjiAirsu
         * @Description //TODO 校验token是否过期
         * @Param token
         * @return 0 有效 1 失效 2校验失败
         */
        public static boolean validToken(String token){
            try {
                if (StringUtils.isEmpty(token)){return false;}
                //解析token
                JWSObject jwsObject = JWSObject.parse(token);
                //获取到载荷
                Payload payload = jwsObject.getPayload();
                JWSVerifier jwsVerifier =new MACVerifier(SECRET_KEY);
                //判断token
                if (jwsObject.verify(jwsVerifier)){
                    JSONObject jsonObject = payload.toJSONObject();
                    //判断token是否过期
                    if (jsonObject.containsKey(INVALID_TIME_KEY)){
                        Long invalidTime = Long.valueOf(jsonObject.get(INVALID_TIME_KEY).toString());
                        Long nowTime = new Date().getTime();
                        //判断是否过期
                        if (invalidTime>nowTime){
                            return true;
                        }

                    }
                }
                return false;
            }catch (Exception e){
                e.printStackTrace();
                return false;
            }
        }

}
